<?php

namespace app\common\service;

use app\common\exception\MiException;
use app\common\service\traits\InstanceTrait;
use app\model\site\User;
use app\model\store\DistRewardLog;
use app\model\store\Order;
use app\model\store\StoreManager;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\db\Query;
use think\facade\Db;

class CommonStoreManagerService
{

    use InstanceTrait;

    /** 团队查询
     * @param int $storeManagerId
     * @param string $levelType
     * @return Query
     */
    public function teamQuery(int $storeManagerId, string $levelType=''): Query
    {
        $levelWhere = "2,3";    // 默认向下查询两级
        if ($levelType == 'one'){
            $levelWhere = "2";
        }elseif ($levelType == 'two'){
            $levelWhere = "3";
        }

        return Db::table(" (
	SELECT
		@ids AS _ids,
		@l:=@l+1 AS level,
		(SELECT @ids := GROUP_CONCAT( id ) FROM `store_manager` WHERE FIND_IN_SET( parent_id, @ids )) cids 
	FROM
		`store_manager`,
		( SELECT @ids:=$storeManagerId , @l:=0) pid 
	) AS scope,
	`store_manager`  ")
            ->whereRaw(" scope._ids IS NOT NULL AND FIND_IN_SET( `store_manager`.id, scope._ids ) AND FIND_IN_SET(level, '$levelWhere') AND store_manager.id<>$storeManagerId ");
    }


    /**
     * 样品基金抵扣
     * @param array $order
     * @param User $user
     * @param StoreManager $storeManager
     * @return array
     */
    public function computeOrderStoreManagerPrice(array $order, User $user, StoreManager $storeManager): array
    {
        $distConfig = CommonSiteConfigService::instance()->getConfigValue($storeManager->site_id, CommonSiteConfigService::DIST);
        if (!$distConfig['is_on'] || !$distConfig['is_on_store_manager']){ // 未开启分销 || 未开启店长
            return $order;
        }
        if ($storeManager->status !=1){ // 店长被禁用，不计算
            return $order;
        }

        // 按订单中每种商品的整数金额抵扣，计算出样品基金最高可抵扣的金额
        $maxManagerPrice = 0;
        foreach ($order['items'] as &$v){
            // 抵扣金额向下取整，如果金额小于1，则不抵扣
            $v['maxManagerPrice'] = floor($v['pay_price']);
            $maxManagerPrice += $v['maxManagerPrice'];
        }

        // 实际可抵扣的样品基金金额
        $managerPrice = min($maxManagerPrice, floor($storeManager->balance*0.1));
        if ($managerPrice==0){  // 抵扣金额为0，不计算，直接返回订单信息
            return $order;
        }

        // 计算订单中每种商品的实际抵扣金额
        foreach ($order['items'] as &$v){
            // 向下取整
            $v['store_manager_price'] = floor($v['maxManagerPrice'] / $maxManagerPrice * $managerPrice);
            $v['pay_price'] = $v['pay_price'] - $v['store_manager_price'];
        }


        // 重新计算订单数据
        $totalPrice = 0;
        $payPrice = 0;
        $managerPrice = 0;
        foreach ($order['items'] as $item){
            $totalPrice += $item['total_price'];
            $payPrice += $item['pay_price'];
            $managerPrice += $item['store_manager_price'];
        }
        $order['total_price'] = $totalPrice;
        $order['pay_price'] = $payPrice;
        $order['store_manager_price'] = $managerPrice;
        return $order;
    }


    /** 释放冻结的佣金
     * @param string $month 格式：2023-12
     * @return void
     * @throws DbException
     */
    public function freeStoreManagerPrice(string $month){
        Db::table('user')->chunk(100, function($users) use($month) {
            foreach ($users as $user) {
                $uid = $user['id'];
                // 允许释放的佣金总金额
                $amount = DistRewardLog::where('user_id', $uid)
                    ->where('status',0)
                    ->whereMonth('create_time', $month)->sum('amount');
                // 释放冻结的佣金
                DistRewardLog::where('user_id', $uid)
                    ->where('status',0)
                    ->whereMonth('create_time',$month)->update([
                    'status' =>1,
                ]);
                // 增加可用佣金金额
                $reward = $user['reward'] + $amount;

                // 店长
                $storeManager = StoreManager::where('user_id', $uid)->find();
                if ($storeManager){
                    // 店长所有下级店长的总业绩（下级店长的所有会员的消费总金额）
                    $totalOrderPrice = $this->getTotalPriceByManagerId($storeManager->id, $month);
                    // 店长返利比例
                    $rate = $this->getManagerRate($storeManager->id, $month);
                    // 为店长返利
                    if ($rate>0 && $totalOrderPrice>0){
                        // 返利金额
                        $managerReward = round($totalOrderPrice * $rate, 2);
                        // 增加可用佣金余额
                        $reward += $managerReward;
                        // 创建佣金明细
                        DistRewardLog::create([
                            'site_id' => $storeManager->site_id,
                            'user_id' => $storeManager->user_id,
                            'from_user_id' => 0,
                            'rel_id' => 0,
                            'rel_model' => '',
                            'reward_type' => 5,
                            'note' => '店长业绩',
                            'amount' => $managerReward,
                            'rate' => $rate,
                            'price' => $totalOrderPrice,
                            'status' => 1,  // 直接释放佣金
                        ]);
                    }
                }
                // 更新账户可用佣金金额
                User::update(['reward'=>$reward], ['id'=>$uid]);

            }
        });

    }

    /**
     * 根据店长id获得指定月份中，其所有下级店长的总业绩之和
     * @param $managerId
     * @param string $month 月份字符串，如：2023-11
     * @return mixed
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getTotalPriceByManagerId($managerId, string $month=''): mixed
    {
        // 查询下级所有的团长的user_id集合
        $uids = StoreManager::where('parent_id', $managerId)->column('user_id');
        $total = 0;
        foreach ($uids as $uid){
            $total += $this->getTotalOrderPriceByParentUidAndMonth($uid, $month);
        }
        return $total;
    }

    /**
     * 根据店长的user_id获取其指定月份的总业绩
     * @param int $parentUid
     * @param string $month
     * @return mixed
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getTotalOrderPriceByParentUidAndMonth(int $parentUid, string $month = ''): mixed
    {
        // 团队中所有的下级id
        $childrenUids = CommonDistService::instance()->teamQuery($parentUid)->column("id");
        $field = " SUM(total_price) - SUM(refund_price) AS sumPrice ";
        if ($month){
            // 团队消费总金额
            $res =  Order::field($field)
                ->where('user_id', 'in', $childrenUids)
                ->whereMonth('pay_time', $month)
                ->find();
        }else{
            $res =  Order::field($field)
                ->where('user_id', 'in', $childrenUids)
                ->find();
        }

        if ($res){
            return $res['sumPrice'];
        }else{
            return 0;
        }
    }

    /**
     * 店长业绩返利比例
     * @param $parentManagerId
     * @param string $month 格式：2023-12
     * @return mixed
     * @throws DbException
     */
    public function getManagerRate($parentManagerId, string $month): mixed
    {
        $rate = 0;
        // 当前店长邀请的店长总数量
        $totalNum = StoreManager::where('parent_id', $parentManagerId)->where('audit_status', 1)->count();
        // 本月邀请的店长的数量
        $monthNum = $this->getManagerNumMonth($parentManagerId, $month);
        if ($totalNum < 3){ // 小于3人
            $rate = 0.01;
        }elseif($totalNum == 3){    // 等于3人
            $rate = 0.03;
        }else{
            // 邀请的店长总数大于3人的逻辑
            $validNum = min($totalNum - 3, $monthNum);
            $maxRate = 0.03 + 0.01*$validNum;
            // 最多返8%
            $rate = min(0.08, $maxRate);
        }

        return $rate;

    }

    /**
     * 本月邀请店长的数量
     * @param $storeManagerId
     * @param string $month
     * @return void
     * @throws DbException
     */
    public function getManagerNumMonth($storeManagerId, string $month){
        return StoreManager::where('parent_id', $storeManagerId)->where('audit_status', 1)->whereMonth('create_time', $month)->count();
    }

}
